﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace wc
{
   public class Program
    {

        //定义字段
        string[] commandArray = { "-c", "-w", "-l", "-o","-e","-a","-s" };          //指定命令集数组
        int fileAllChars, fileWordCount, fileLineCount;                             //字符总数，单词总数，行数
        List<string> fileArray = new List<string>();                                //多批量处理文件表
        List<string> lstExceptWords = new List<string>();                           //隔离单词
        List<string> lstAllWord = new List<string>();                               //文件中总单词
        int noteLine = 0;                                                           //文件中的注释行
        int emptyLine = 0;                                                          //文件中的空行
        int codeLine = 0;                                                           //文件中的代码行
        int re = 0;
        public static void Main(string[] args)
        {
            if (!File.Exists("savefilepath.txt"))                                    //储存文件路径信息文件是否存在，否则创建      
            {
                FileStream sFP = new FileStream("savefilepath.txt", FileMode.Create);
                string savefilename = "result.txt";                                 //默认储存文件
                byte[] filePath = Encoding.Default.GetBytes(savefilename);          
                sFP.Write(filePath, 0, filePath.Length);
                sFP.Close();
            }
            if (!File.Exists("result.txt"))                                         //储存文件是否存在，否则创建     
            {
                FileStream sFP = new FileStream("result.txt", FileMode.Create);

                sFP.Close();
            }

            int maxLength = args.Length;                                             //接受args数组，判断参数个数
            bool isExceptWord=false;                                                  //是否含有除开单词 
            bool isBatch = false;                                                     //是否用批处理  
            int commandO=0;                                                            //-o命令所在索引
            int batchSuffix = 0;                                                       //.用批处理文后缀索引  
            int singleFile = 0;                                                        //单文件路径
                                                                                       //字段初始化
            Program p = new Program();
            //特殊命令符检查
            for(int i=0;i<args.Length;i++)
            {
                if (args[i] == "-e")
                {
                    isExceptWord = true;
                    commandO = i;
                }
                else if(args[i]=="-s")
                {
                    isBatch = true;
                    for(int j=i+1;j<args.Length;j++)
                    {
                        if(args[j]!= "-c"&&args[j] != "-w" && args[j] != "-l" && args[j] !="-a")
                        {
                            batchSuffix = j;
                            break;
                        }
                    }
                }
                else if(args[i]=="-o")
                {
                    p.setSaveFileName(args[i+1]);
                }
            }
            Console.WriteLine(isBatch);
            //如果有除开单词，执行以下命令
            if(isExceptWord)
            {
                p.ExceptWords(args[commandO+1]);
            }
            //如果有用批处理命令，执行以下命令
            if(isBatch)
            {
                p.FindAllFiles(Directory.GetCurrentDirectory(),args[batchSuffix]);
            }
            else if(!isBatch)
            {
                for (int i=0; i < args.Length; i++)
                {
                    if (args[i] != "-c" && args[i] != "-w" && args[i] != "-l" && args[i] != "-a")
                    {
                        singleFile = i;
                    }
                }
                p.fileArray.Add(args[singleFile]);
            }
            //开始按命令执行
            for(int i=0;i<p.fileArray.Count;i++)
            {
                string[] filename = p.fileArray[i].Split('\\');
                string str = filename[filename.Length-1];
                for(int j=0;j<args.Length;j++)
                {
                    if(args[j]=="-a")
                    {
                        p.EmptyLine(p.fileArray[i]);
                        p.NoteLine(p.fileArray[i]);
                        p.CodeLine(p.fileArray[i]);
                        p.saveData(p.getSaveFileName(), "代码行/空行/注释行", p.codeLine.ToString()+"/"+ p.emptyLine.ToString() + "/" + p.noteLine.ToString(), str);
                        p.emptyLine = 0;
                        p.noteLine = 0;
                        p.codeLine = 0;
                        p.re = 0;
                        p.fileLineCount = 0;
                    }
                    if (args[j] == "-c")
                    {
                        p.charCount(p.fileArray[i]);
                        p.saveData(p.getSaveFileName(), "字符总数", p.fileAllChars.ToString(), str);
                        p.fileAllChars = 0;
                    }
                    else if (args[j] == "-w")
                    {
                        p.wordCount(p.fileArray[i]);
                        p.saveData(p.getSaveFileName(), "单词数", p.fileWordCount.ToString(), str);
                        p.fileWordCount = 0;
                        p.lstAllWord.Clear();

                    }
                    else if (args[j] == "-l")
                    {
                        p.lineCount(p.fileArray[i]);
                        p.saveData(p.getSaveFileName(), "总行数", p.fileLineCount.ToString(), str);
                        p.fileLineCount=0;
                    }
                    else continue;

                }
            }



        }
        


        /// <summary>
        /// 总字符数，包括特殊字符以及'\r''\n'回车符和换行符和FE FFunicode编译字符
        /// </summary>
        /// <param name="fileName"></param>
        public void charCount(string fileName)
        {
            Stream file = new FileStream(fileName, FileMode.Open);
            fileAllChars = (int)file.Length;
            file.Close();

        }


        /// <summary>
        /// 单词总数
        /// </summary>
        /// <param name="fileName"></param>
        public void wordCount(string filepath)
        {

            bool isWord = false;
            int index = 0;
            string str = string.Empty;
            FileStream fs = new FileStream(filepath, FileMode.Open);
            char[] allChars = new char[fs.Length];
            byte[] AllChars = new byte[fs.Length];
            fs.Read(AllChars, 0, AllChars.Length);
            Decoder d = Encoding.Default.GetDecoder();
            d.GetChars(AllChars, 0, AllChars.Length, allChars, 0);
            for (int i = 0; i < AllChars.Length; i++)
            {

                if (allChars[i] != ' ' && allChars[i] != ',' && allChars[i] != ';' && allChars[i] != '\n' && allChars[i] != '\r' && isWord == false)
                {
                    isWord = true;
                    index = i;
                }
                if (isWord && (allChars[i] == ' ' || allChars[i] == ',' || allChars[i] == ';' || allChars[i] == '\n' || allChars[i] == '\r'))
                {
                    for (int j = index; j < i; j++)
                    {
                        str = string.Concat(str, allChars[j]);
                    }
                    lstAllWord.Add(str);
                    str = string.Empty;
                    isWord = false;
                }
            }
            fs.Close();
            fileWordCount = lstAllWord.Count;
            for(int i=0;i<lstAllWord.Count;i++)
            {
                for(int j=0;j<lstExceptWords.Count;j++)
                {
                    if(lstAllWord[i]==lstExceptWords[j])
                    {
                        fileWordCount--;
                    }
                }
            }
        }


        /// <summary>
        /// 总行数
        /// </summary>
        /// <param name="fileName"></param>
        public void lineCount(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Open);                            //创建文件流，格式为打开
            StreamReader sr = new StreamReader(fs);                                             //创建阅读器
            while (sr.ReadLine() != null)                                                       //读取一行，直至非空
            {
                fileLineCount++;
            }
            sr.Close();                                                                         //关闭阅读器和文件流
            fs.Close();
        }


        /// <summary>
        /// 储存数据
        /// </summary>
        /// <param name="fileName"></param>
        public void saveData(string filePath,string strType,string count,string filename)
        {
            string data ="文件名："+filename+","+ strType + ":" + count+'\r'+'\n';
            byte[] myData = Encoding.Default.GetBytes(data);

            if (!File.Exists(filePath))
            {
                FileStream createFile = new FileStream(filePath, FileMode.Create);
                createFile.Close();

            }

            FileStream savaFile = new FileStream(filePath, FileMode.Append);

            savaFile.Write(myData, 0, myData.Length);

            savaFile.Close();
        }

        
        /// <summary>
        /// 得到指定文件目录的路径
        /// </summary>
        /// <returns></returns>
        public string getSaveFileName()
        {
            FileStream sFP = new FileStream("savefilepath.txt", FileMode.Open);                 //打开savefilepath文件
            string savefilepath = string.Empty;
            byte[] filename = new byte[sFP.Length];
            sFP.Read(filename, 0, filename.Length);                                             //将路径信息文件转化为byte数组储存
            savefilepath = Encoding.Default.GetString(filename);                                //将byte数组转化为字符串
            sFP.Close();
            return savefilepath;
        }


        /// <summary>
        /// 将指定文件目录加入到储存文件路径信息文件中
        /// </summary>
        /// <param name="fileName"></param>
        public void setSaveFileName(string filepath)
        {
            FileStream sFP = new FileStream("savefilepath.txt", FileMode.Create);               //创建savefilepath文件，直接覆盖原有文件
            string savefilename = filepath;
            byte[] filePath = Encoding.Default.GetBytes(savefilename);                          //将新的储存文件名转化为byte数组
            sFP.Write(filePath, 0, filePath.Length);                                            //将新的储存文件名写入
            sFP.Close();
        }


        /// <summary>
        /// 遍历同目录下所有的符合文件
        /// </summary>
        public void FindAllFiles(string path,string searchstr)
        {
            string[] strfile = Directory.GetFiles(path,searchstr,SearchOption.AllDirectories);//获取当前目录以及子目录中符合条件的文件
            foreach (string str in strfile)
            {
                fileArray.Add(str);                                                           //将符合的文件添加到集合中
            }
            
        }

        /// <summary>
        /// 查询脚本中的空行
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public void EmptyLine(string filePath)
        {
            int n = 0;
            int oldIndex=0;
            FileStream fs = new FileStream(filePath, FileMode.Open);
            char[] allChars = new char[fs.Length];
            byte[] AllChars = new byte[fs.Length];
            fs.Read(AllChars,0,AllChars.Length);
            Decoder decoder = Encoding.Default.GetDecoder();
            decoder.GetChars(AllChars,0,allChars.Length,allChars,0);
            for(int i=0;i<allChars.Length;i++)
            {
                if (allChars[i] == '\n' && n != 1)
                {
                    n = 1;
                    oldIndex = i;
                }
                if (n == 1 && allChars[i] != '\n' && allChars[i] != '\r' && allChars[i] != '}' && allChars[i] != '{' && allChars[i] != ' ')
                {
                    for (int j = oldIndex + 1; j < i; j++)
                    {
                        if (allChars[j] == '\n')
                        {
                            emptyLine++;
                        }
                        if ((allChars[j] == ' ' || allChars[j] == '}') && j == i - 1)
                        {
                            emptyLine++;
                        }
                    }
                    n = 0;
                }
                if (i < allChars.Length - 2)
                {
                    if (allChars[i] == '}' && allChars[i + 1] == '/')
                        emptyLine--;
                }
                
            }
            fs.Close();
        }

        /// <summary>
        /// 查询脚本中的代码行
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public void CodeLine(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open);                            //创建文件流，格式为打开
            StreamReader sr = new StreamReader(fs);                                             //创建阅读器
            while (sr.ReadLine() != null)                                                       //读取一行，直至非空
            {
                fileLineCount++;
            }
            sr.Close();                                                                         //关闭阅读器和文件流
            fs.Close();
            codeLine = fileLineCount - emptyLine-noteLine+re;

        }

        /// <summary>
        /// 查询脚本中的注释行
        /// </summary>
        /// <param name="filePath"></param>
        public void NoteLine(string filePath)
        {
            int n = 0,m=0;
            int oldIndex = 0;
            FileStream fs = new FileStream(filePath, FileMode.Open);
            char[] allChars = new char[fs.Length];
            byte[] AllChars = new byte[fs.Length];
            fs.Read(AllChars, 0, AllChars.Length);
            Decoder decoder = Encoding.Default.GetDecoder();
            decoder.GetChars(AllChars, 0, allChars.Length, allChars, 0);
            for (int i = 0; i < allChars.Length; i++)
            {
                if (allChars[i] == '\n' && n == 1)
                {
                    n = 2;
                    oldIndex = i;
                }
                if (i < allChars.Length - 1)
                {
                    if (allChars[i] == '/' && allChars[i + 1] == '/')
                    {
                        if (n == 0)
                        {
                            for (int j = oldIndex; j < i; j++)
                            {
                                if (allChars[j] != '\n' && allChars[j] != '\r' && allChars[j] != '}' && allChars[j] != '{' && allChars[j] != ' ' && allChars[j] != '/')
                                {
                                    re++;
                                    break;
                                }
                            }
                        }
                        noteLine++;
                        for (int j = oldIndex; j < i; j++)
                        {
                            if (n == 2 && allChars[j] != '\n' && allChars[j] != '\r' && allChars[j] != '}' && allChars[j] != '{' && allChars[j] != ' ' && allChars[j] != '/')
                            {
                                re++;
                                break;
                            }
                        }
                        n = 1;
                    }
                    if ((allChars[i] == '\n' ||allChars[i]=='}')&& allChars[i + 1] == '/')
                    {
                        re--;
                    }
                }
              

            }
            fs.Close();
        }
        
        
        /// <summary>
        /// 添加除去的单词
        /// </summary>
        /// <param name="filepath"></param>
        public void ExceptWords(string filepath)
        {
            bool isWord=false;
            int index = 0;
            string str = string.Empty;
            FileStream fs = new FileStream(filepath, FileMode.Open);
            char[] allChars = new char[fs.Length];
            byte[] AllChars = new byte[fs.Length];
            fs.Read(AllChars,0,AllChars.Length);
            Decoder d = Encoding.Default.GetDecoder();
            d.GetChars(AllChars, 0, AllChars.Length, allChars, 0);
            for(int i=0;i<AllChars.Length;i++)
            {
                
                if(allChars[i]!=' '&&allChars[i]!=','&&allChars[i]!=';'&&allChars[i]!='\n'&&allChars[i]!='\r'&&isWord==false)
                {
                    isWord = true;
                    index = i;
                }
                if(isWord&&(allChars[i] == ' ' || allChars[i] == ',' || allChars[i] == ';' || allChars[i] == '\n'|| allChars[i] == '\r'))
                {
                    for(int j=index;j<i;j++)
                    {
                        str = string.Concat(str,allChars[j]);
                    }
                    lstExceptWords.Add(str);
                    str = string.Empty;
                    isWord = false;
                }
            }
            fs.Close();

        }

  


    }
}
